package authentication;

import java.util.logging.Level;
import java.util.logging.Logger;

import javax.persistence.EntityManager;
import javax.persistence.Query;

import org.apache.openjpa.persistence.NoResultException;

import infrastructure.exceptions.SessionException;
import dal.JPAAgent;
import dal.User;
import remote.Session;
import remote.SessionManager;

public class AuthenticationManager {
	
	private static AuthenticationManager _theInstance = new AuthenticationManager();
	
	// keeps guest user
	private static final User GUEST_USER = new User("guest","guest");
	
	protected AuthenticationManager(){}
	
	
	public static AuthenticationManager getInstance(){
		return _theInstance;
	}
	/**
	 * @param id - session id for which to get the session 
	 * @return if <code> id </code> identifies any open session, it is returned, 
	 * otherwise guest session is returned
	 */
	public Session getSession(Session.SessionId id){
		
		// Check is session exists 
		if (SessionManager.getInstance().isSessionExists(id)){
			try{
				return SessionManager.getInstance().getSession(id);
			}catch(SessionException ex){
				return SessionManager.getGuestSession();
			}			
		}else{
			return SessionManager.getGuestSession();
		}
	}
	
	/**
	 * This method tries to perform a login operation
	 * @param user - user to authenticate 
	 * @return  authenticated user session, or guest user if no authentication failed
	 */
	public Session authenticate(String userName,String password){
		
		try{
			EntityManager entityManager = JPAAgent.getInstance().getEntityManagerFactory().createEntityManager();
			
			User realUser;
			
			try{
				Query getUserByIdQuerry = 
					entityManager.createQuery("SELECT x FROM USERS x WHERE x.username = '" + userName + 
							"' AND x.password = '" +password + "'");
				
				realUser = (User)getUserByIdQuerry.getSingleResult();				
			}catch(NoResultException noREsultEx){
				Logger.getLogger(this.getClass().getName()).logp(Level.WARNING, this.getClass().getName(), 
						"authenticate", "Authentication failed for user '" + userName + "'",noREsultEx);
				realUser = null;
			}
			
			
			// Check if we get any 
			if (null != realUser){			
				return SessionManager.getInstance().createSession(realUser);
			}else{
				return SessionManager.getGuestSession();
			}
		}catch(Exception ex){
			Logger.getLogger(this.getClass().getName()).logp(Level.WARNING, this.getClass().getName(), 
					"authenticate", "Authentication failed for user '" + userName + "'",ex);
			return SessionManager.getGuestSession();
		}
		
	}
	
	public User getGuestUser(){
		return GUEST_USER;
	}
	
	public boolean isAdministrator(User userToCheck){
		return userToCheck.isAdministrator();
	}
	
	public boolean isGuestUser(User userToCheck){
		return userToCheck == getGuestUser();
	}
}
